// 1	布尔型
// 布尔型的值只可以是常量 true 或者 false。一个简单的例子：var b bool = true。
// 2	数字类型
// 整型 int 和浮点型 float32、float64，Go 语言支持整型和浮点型数字，并且支持复数，其中位的运算采用补码。
// 3	字符串类型:
// 字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。
// 4	派生类型:
// 包括：
// (a) 指针类型（Pointer）
// (b) 数组类型
// (c) 结构化类型(struct)
// (d) Channel 类型
// (e) 函数类型
// (f) 切片类型
// (g) 接口类型（interface）
// (h) Map 类型
package main

import "fmt"

var b bool = true
var i int = 10
var f float32 = 3.14
var s string = "Hello, world!"

// 指针类型
var p *int = &i

// 数组类型
var arr [5]int = [5]int{1, 2, 3, 4, 5}

// 结构化类型
type Person struct {
	name string
	age  int
}

var p1 Person = Person{"Alice", 25}

// Channel 类型
var ch chan int

// 函数类型
func add(x int, y int) int {
	return x + y
}

// 切片类型
var sl []int = []int{1, 2, 3, 4, 5}

// 接口类型
type Animal interface {
	Speak()
}
type Dog struct {
	name string
}

func (d Dog) Speak() {
	fmt.Println(d.name, " says woof!")
}

type Cat struct {
	name string
}

func (c Cat) Speak() {
	fmt.Println(c.name, " says meow!")
}

var a Animal = Dog{"Buddy"}

// Map 类型
var mp map[string]int = map[string]int{"apple": 5, "banana": 7}

// 运算符
// 1. 算术运算符：+、-、*、/、%、++、--
// 2. 关系运算符：==、!=、<、<=、>、>=
// 3. 逻辑运算符：&&、||、!
// 4. 赋值运算符：=、+=、-=、*=、/=、%=
// 5. 位运算符：&、|、^、<<、>>、&^
// 6. 其他运算符：:=、()、[]、.、->、<-、?:、make、new、len、cap、append、copy、close、delete、complex、real、imag、panic、recover
// 7. 运算符优先级：
// 1. 后缀表达式：++、--、函数调用、索引、成员访问、类型断言、make、new、len、cap、append、copy、close、delete、complex、real、imag、panic、recover
// 2. 乘除运算符：*、/、%
// 3. 加减运算符：+、-
// 4. 移位运算符：<<、>>
// 5. 关系运算符：==、!=、<、<=、>、>=
// 6. 位运算符：&、|、^、&^
// 7. 逻辑运算符：&&、||
// 8. 赋值运算符：=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=
// 9. 条件运算符：?:
// 控制结构
// 1. if-else 语句
// 2. for 循环
// 3. switch-case 语句
// 4. 标签语句
// 5. defer 语句
// 6. go 语句
// 7. 空语句：即分号
// 指针类型
// 1. 指针类型声明：var p *int = &i;
// 2. 指针类型使用：*p 取指针指向的变量的值，p 指针变量的地址，&i 取变量的地址。
// 3. 指针类型作为函数参数：func add(x *int, y int) int { return *x + y; }
// 4. 指针类型作为结构体成员：type Person struct { name string; age int; ptr *int; }
// 5. 指针类型作为数组成员：var arr [5]*int = [5]*int{&i, &j, &k, &l, &m};
// 6. 指针类型作为切片成员：var sl []*int = []*int{&i, &j, &k, &l, &m};
// 7. 指针类型作为 map 成员：var mp map[*int]string = map[*int]string{&i: "apple", &j: "banana"};
// 数组类型
// 1. 数组类型声明：var arr [5]int = [5]int{1, 2, 3, 4, 5};
// 2. 数组类型使用：arr[0] 取数组第一个元素，arr[1:3] 取数组第二个到第三个元素。
// 3. 数组类型作为函数参数：func printArr(arr [5]int) { for i := 0; i < len(arr); i++ { fmt.Println(arr[i]); } }
// 4. 数组类型作为结构体成员：type Person struct { name string; age int; arr [5]int; }
// 5. 数组类型作为切片成员：var sl []int = []int{1, 2, 3, 4, 5}; var sl2 []int = sl[1:3];
// 结构化类型
// 1. 结构化类型声明：type Person struct { name string; age int; }
// 2. 结构化类型使用：p1.name 取结构体成员 name 的值，p1.age 取结构体成员 age 的值。
// 3. 结构化类型作为函数参数：func printPerson(p Person) { fmt.Println(p.name, p.age); }
// 4. 结构化类型作为数组成员：var arr [5]Person = [5]Person{{"Alice", 25}, {"Bob", 30}, {"Charlie", 35}, {"David", 40}, {"Eve", 45}};
// 5. 结构化类型作为切片成员：var sl []Person = []Person{{"Alice", 25}, {"Bob", 30}, {"Charlie", 35}, {"David", 40}, {"Eve", 45}};
// 6. 结构化类型作为 map 成员：var mp map[string]Person = map[string]Person{"Alice": {"Alice", 25}, "Bob": {"Bob", 30}};
// Channel 类型
// 1. Channel 类型声明：var ch chan int;
// 2. Channel 类型使用：ch <- 1 向 Channel 发送数据，<-ch 从 Channel 接收数据。
// 3. Channel 类型作为函数参数：func printChan(ch chan int) { for i := 0; i < 5; i++ { fmt.Println(<-ch); } }
// 4. Channel 类型作为结构体成员：type Person struct { name string; age int; ch chan int; }
// 5. Channel 类型作为切片成员：var sl []chan int = []chan int{make(chan int), make(chan int), make(chan int)};
// 函数类型
// 1. 函数类型声明：func add(x int, y int) int { return x + y; }
// 2. 函数类型使用：add(1, 2) 调用函数，add(p1.ptr, 10) 调用指针函数。
// 3. 函数类型作为结构体成员：type Person struct { name string; age int; add func(int, int) int; }
// 4. 函数类型作为切片成员：var sl []func(int, int) int = []func(int, int) int{add, sub, mul, div};
// 切片类型
// 1. 切片类型声明：var sl []int = []int{1, 2, 3, 4, 5};
// 2. 切片类型使用：sl[0] 取切片第一个元素，sl[1:3] 取切片第二个到第三个元素。
// 3. 切片类型作为函数参数：func printSlice(sl []int) { for i := 0; i < len(sl); i++ { fmt.Println(sl[i]); } }
// 4. 切片类型作为结构体成员：type Person struct { name string; age int; sl []int; }
// 5. 切片类型作为数组成员：var arr [5]int = [5]int{1, 2, 3, 4, 5}; var arr2 [3]int = arr[1:3];
// 接口类型
// 1. 接口类型声明：type Animal interface { Speak(); }
// 2. 接口类型使用：var a Animal = Dog{"Buddy"}; a.Speak() 调用接口方法。
// 3. 接口类型作为函数参数：func printAnimal(a Animal) { a.Speak(); }
// 4. 接口类型作为结构体成员：type Person struct { name string; age int; a Animal; }
// 5. 接口类型作为切片成员：var sl []Animal = []Animal{Dog{"Buddy"}, Cat{"Mimi"}};
// Map 类型
// 1. Map 类型声明：var mp map[string]int = map[string]int{"apple": 5, "banana": 7};
// 2. Map 类型使用：mp["apple"] 取 Map 中键为 "apple" 的值。
// 3. Map 类型作为函数参数：func printMap(mp map[string]int) { for k, v := range mp { fmt.Println(k, v); } }
// 4. Map 类型作为结构体成员：type Person struct { name string; age int; mp map[string]int; }
// 5. Map 类型作为切片成员：var sl []string = []string{"apple", "banana", "orange"}; var sl2 []int = []int{5, 7, 9}; var mp map[string]int = map[string]int{"apple": 5, "banana": 7, "orange": 9}; var sl3 []int = []int{mp[sl[0]], mp[sl[1]], mp[sl[2]]};
// 运算符
// 1. 算术运算符：+、-、*、/、%、++、--
// 2. 关系运算符：==、!=、<、<=、>、>=
// 3. 逻辑运算符：&&、||、!
// 4. 赋值运算符：=、+=、-=、*=、/=、%=
// 5. 位运算符：&、|、^、<<、>>、&^
// 6. 其他运算符：:=、()、[]、.、->、<-、?:、make、new、len、cap、append、copy、close、delete、complex、real、imag、panic、recover
// 7. 运算符优先级：
// 1. 后缀表达式：++、--、函数调用、索引、成员访问、类型断言、make、new、len、cap、append、copy、close、delete、complex、real、imag、panic、recover
// 2. 乘除运算符：*、/、%
// 3. 加减运算符：+、-
// 4. 移位运算符：<<、>>
// 5. 关系运算符：==、!=、<、<=、>、>=
// 6. 位运算符：&、|、^、&^
// 7. 逻辑运算符：&&、||
// 8. 赋值运算符：=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=
// 9. 条件运算符：?:
// 控制结构
// 1. if-else 语句
// 2. for 循环
// 3. switch-case 语句
// 4. 标签语句
// 5. defer 语句
// 6. go 语句
// 7. 空语句：即分号
// 指针类型
// 1. 指针类型声明：var p *int = &i;
// 2. 指针类型使用：*p 取指针指向的变量的值，p 指针变量的地址，&i 取变量的地址。
// 3. 指针类型作为函数参数：func add(x *int, y int) int { return *x + y; }
// 4. 指针类型作为结构体成员：type Person struct { name string; age int; ptr *int; }
// 5. 指针类型作为数组成员：var arr [5]*int = [5]*int{&i, &j, &k, &l, &m};
// 6. 指针类型作为切片成员：var sl []*int = []*int{&i, &j, &k, &l, &m};
// 7. 指针类型作为 map 成员：var mp map[*int]string = map[*int]string{&i: "apple", &j: "banana"};
// 数组类型
// 1. 数组类型声明：var arr [5]int = [5]int{1, 2, 3, 4, 5};
// 2. 数组类型使用：arr[0] 取数组第一个元素，arr[1:3] 取数组第二个到第三个元素。
// 3. 数组类型作为函数参数：func printArr(arr [5]int) { for i := 0; i < len(arr); i++ { fmt.Println(arr[i]); } }
// 4. 数组类型作为结构体成员：type Person struct { name string; age int; arr [5]int; }
